package training.osms.persistence.hibernate;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;

import training.framework.presentation.AbstractEntityDao;
import training.osms.business.model.Product;
import training.osms.business.model.ProductSearchOptions;
import training.osms.business.model.Product_;
import training.osms.persistence.EntityManagerFactorySingleton;

public class ProductDAO extends
		AbstractEntityDao<Integer, Product, ProductSearchOptions> {
	
	public ProductDAO(){
		super(EntityManagerFactorySingleton.FACTORY, Product.class);
	}

	@Override
	protected Order toOrder(CriteriaBuilder builder, Root<Product> root) {
		return builder.asc(root.get(Product_.name));
	}

	@Override
	protected Predicate toPredicate(CriteriaBuilder builder,
			Root<Product> root, ProductSearchOptions options) {
		
		Predicate namePredicate;
		String productName = options.getName();
		if (StringUtils.isBlank(productName)) {
			namePredicate = builder.conjunction();								
		} else {
			namePredicate = builder.like(
				builder.lower(root.get(Product_.name)), 
				toLikeParameter(productName)
			);
		}
		
		Predicate descriptionPredicate;
		String productDescription = options.getDescription();	
		if(StringUtils.isBlank(productDescription)){
			descriptionPredicate = builder.conjunction();
		}else{
			descriptionPredicate = builder.like(
					builder.lower(root.get(Product_.description)),
					toLikeParameter(productDescription)
			);
		}
		
		Predicate pricePredicate;
		String productPrice = options.getDescription();
		if(StringUtils.isBlank(productPrice)){
			pricePredicate = builder.conjunction();
		}else{
			pricePredicate = builder.like(
					builder.lower(root.get(Product_.description)),
					toLikeParameter(productPrice)
			);
		}
		
		Predicate predicate = builder.and(namePredicate, descriptionPredicate, pricePredicate);
		
		return predicate;
	}

	public Product selectProduct(String productName) {

		StringBuilder jpql = new StringBuilder("select p from ");
		jpql.append(Product.class.getName());
		jpql.append(" p where trim(lower(p.name)) = :productName");
		EntityManager manager = null;
		try {
			manager =  EntityManagerFactorySingleton.FACTORY.createEntityManager();
			TypedQuery<Product> query = manager.createQuery(jpql.toString(), Product.class);
			query.setParameter("productName", productName.toLowerCase().trim());
			List<Product> result = query.getResultList();
			if (result.isEmpty()) {
				return null;
			} else {
				return result.get(0);
			}
		} finally {
			if (manager != null) {
				try {
					manager.close();
				} catch (RuntimeException e) {}
			}
		}				
	}
	
}
